﻿#region Header

/*
Copyright (c) 2015, G.W. van der Vegt
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
  the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of G.W. van der Vegt nor the names of its contributors may be
  used to endorse or promote products derived from this software without specific prior written
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#endregion Header

namespace SharpUAC
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Principal;
    using System.Windows.Forms;

    using Microsoft.Win32.TaskScheduler;

    using Security.Windows.Forms;

    // What seems to perform best is start SharpUAC with a runas link with /savecred
    // (run it once without, enter the password and then run it with the switch from ther on).
    // SharpUAC will now start as the intended user and elevating should only give the notice
    // but not ask for a password.
    // Once elevated Link van best be started with the impersonate button and selecting the original (unaltered) lnk.
    // SharUAC will execute the link with the same level as itself.
    using Swiss;

    /// <summary>
    /// The Main Form.
    /// </summary>
    public partial class Form1 : Form
    {
        #region Fields

        /// <summary>
        /// Error Message.
        /// </summary>
        private static readonly String S_CONSOLE = "You need to have Administrative Priviliges.";

        /// <summary>
        /// Pathname of the folder.
        /// </summary>
        private static readonly String S_FOLDER = "SharpUAC";

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the SharpUAC.Form1 class.
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Creates the scheduled task and a shortcut to it.
        /// <list type="numbered">
        /// <item>In Task Scheduler, right-click "Task Scheduler Library" and select
        /// "New Folder" Name it
        /// whatever you would like.</item>
        /// <item>Select the new folder and click "Create Task" (not "Create Basic
        /// Task")</item>
        /// <item>Name the task something descriptive. Enable "Run with highest
        /// privileges," and select
        /// your OS under "Configure for."</item><item>Under the Actions tab, select
        /// "Start a program" in the Action dropdown if it isn't already. Click
        /// Browse and find your app's .exe file (usually under Program Files on your
        /// C: drive).</item>
        /// <item>(Laptops) Under Conditions tab, deselect "Start the task
        /// only if the computer is on AC power."</item>
        /// <item>On your desktop, right click and select New &gt;
        /// Shortcut.
        /// </item>
        /// <item>Paste 'C:\Windows\System32\schtasks.exe /RUN /TN "Name of folder\
        /// Name of task" into the text box.
        /// </item>
        /// </list>
        /// </summary>
        ///
        /// <param name="lnkfile"> The lnk file. </param>
        public void CreateTask(String lnkfile)
        {
            if (SharpUACHelper.IsAdmin())
            {
                //! 1) Extract info from *.lnk.
                //
                ShellLink sl = new ShellLink(lnkfile);

                String appl = sl.Target;
                String args = sl.Arguments;
                String workdir = sl.WorkingDirectory;
                String uactask = Path.GetFileNameWithoutExtension(sl.ShortCutFile);
                Int32 index = sl.IconIndex;
                String icon = String.IsNullOrEmpty(sl.IconPath) ? sl.Target : sl.IconPath;
                String newlnk = Path.Combine(Path.GetDirectoryName(lnkfile), String.Format("[{0}] {1}.lnk", S_FOLDER, uactask));

                //! 2) Show extracted information.
                //
                ListViewGroup lvg = new ListViewGroup(uactask);
                listView1.Groups.Add(lvg);

                lvg.Items.Add(listView1.Items.Add("Link")).SubItems.Add(lnkfile);
                lvg.Items.Add(listView1.Items.Add("Application")).SubItems.Add(appl);
                lvg.Items.Add(listView1.Items.Add("Arguments")).SubItems.Add(args);
                lvg.Items.Add(listView1.Items.Add("WorkingDirectory")).SubItems.Add(workdir);
                lvg.Items.Add(listView1.Items.Add("IconPath")).SubItems.Add(lnkfile);
                lvg.Items.Add(listView1.Items.Add("Link")).SubItems.Add(icon);
                lvg.Items.Add(listView1.Items.Add("IconIndex")).SubItems.Add(index.ToString());

                lvg.Items.Add(listView1.Items.Add("TaskName")).SubItems.Add(uactask);
                lvg.Items.Add(listView1.Items.Add("New Link")).SubItems.Add(newlnk);

                listView1.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
                listView1.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);

                //! 3) Create Schedule Task.
                //
                using (TaskService ts = new TaskService())
                {
                    String user = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

                    Version ver = ts.HighestSupportedVersion;
                    Boolean newVer = (ver >= new Version(1, 2));

                    //! 4) Create Task.
                    //
                    TaskDefinition td = ts.NewTask();

                    td.Data = uactask;

                    //td.Principal.UserId = "SYSTEM";

                    td.Principal.LogonType = TaskLogonType.InteractiveToken;

                    td.RegistrationInfo.Author = "Wim van der Vegt";
                    td.RegistrationInfo.Description = String.Format(
                        "{0} removes selected Ghosted Devices. \r\n" +
                        "\r\n" +
                        "Default Settings for this scheduled task are:\r\n" +
                        " - Running with the required Administrative Privileges,\r\n" +
                        " - Can be started manually with 'schtasks /run /ts \"{0}/{1}\"'. \r\n" +
                        "\r\n" +
                        "See http://sharpuac.codeplex.com", S_FOLDER, uactask);
                    td.RegistrationInfo.Documentation = "See http://sharpuac.codeplex.com";
                    td.Settings.DisallowStartIfOnBatteries = true;
                    td.Settings.Hidden = false;

                    if (newVer)
                    {
                        td.Principal.RunLevel = TaskRunLevel.Highest;
                        td.RegistrationInfo.Source = SharpUACHelper.S_TITLE;
                        td.RegistrationInfo.URI = new Uri("http://sharpuac.codeplex.com");
                        td.RegistrationInfo.Version = new Version(0, 9);
                        td.Settings.AllowDemandStart = true;
                        td.Settings.AllowHardTerminate = true;
                        td.Settings.Compatibility = TaskCompatibility.V2;
                        td.Settings.MultipleInstances = TaskInstancesPolicy.Queue;
                    }

                    //LogonTrigger lTrigger = (LogonTrigger)td.Triggers.Add(new LogonTrigger());
                    //if (newVer)
                    //{
                    //    lTrigger.Delay = TimeSpan.FromMinutes(1);
                    //    lTrigger.UserId = user;
                    //}

                    //! 5) Create Action.
                    //
                    td.Actions.Add(new ExecAction(appl, args, workdir));

                    //! 6) Make sure the TaskFolder is present.
                    //
                    TaskFolder tf = null;
                    foreach (TaskFolder f in ts.RootFolder.SubFolders)
                    {
                        if (f.Name.Equals(S_FOLDER))
                        {
                            tf = f;
                            break;
                        }
                    }

                    if (tf == null)
                    {
                        tf = ts.RootFolder.CreateFolder(S_FOLDER);
                    }

                    //! 7) Register the task in the new folder.
                    //
                    Task task = tf.RegisterTaskDefinition(
                           uactask,
                           td,
                           TaskCreation.CreateOrUpdate, null, null,
                           TaskLogonType.InteractiveToken,
                           null);

                    //! 8) Show the task Editor.
                    //
                    task.ShowEditor();
                }

                //! 9) Create Replacement Icon.
                //
                using (ShellLink shortcut = new ShellLink())
                {
                    //C:\Windows\System32\schtasks.exe /RUN /TN "USer2\SharpUAC"

                    shortcut.Target = @"%SystemRoot%\System32\schtasks.exe";
                    shortcut.Arguments = String.Format("/RUN /TN \"{0}\\{1}\"", S_FOLDER, uactask);
                    shortcut.WorkingDirectory = sl.WorkingDirectory;
                    shortcut.Description = String.Format("{0} Elevated Shortcut", S_FOLDER);
                    shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmNormal;
                    shortcut.IconPath = icon;
                    shortcut.IconIndex = index;
                    shortcut.DisplayMode = sl.DisplayMode;
                    shortcut.HotKey = sl.HotKey;

                    String lnkPath = Path.Combine(Path.GetDirectoryName(lnkfile), String.Format("[{0}] {1}.lnk", S_FOLDER, uactask));

                    shortcut.Save(lnkPath);
                }
            }
            else
            {
                MessageBox.Show(S_CONSOLE, SharpUACHelper.S_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutDialog().ShowDialog();
        }

        /// <summary>
        /// This loads a shortcut,creates a scheduled task for it and a new shortcut
        /// that runs this newly created task.
        /// </summary>
        ///
        /// <param name="sender"> Source of the event. </param>
        /// <param name="e">      Event information. </param>
        private void ByTaskBtn_Click(object sender, EventArgs e)
        {
            if (SharpUACHelper.IsAdmin())
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    listView1.Items.Clear();
                    foreach (String shortcut in openFileDialog1.FileNames)
                    {
                        CreateTask(shortcut);
                    }
                }
            }
            else
            {
                //! Must run with limited privileges in order to see the UAC window
                SharpUACHelper.RestartElevated(Application.ExecutablePath);
            }
        }

        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ClickOnceUpdater.InstallUpdateSyncWithInfo("http://sharpuac.codeplex.com/releases/view/latest");
        }

        private void createLinkToSharpUACToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (UserCredentialsDialog dialog = new UserCredentialsDialog())
            {
                // Debug.Print(dialog.MachineName);

                dialog.LoadCredentials("localhost", false);

                try
                {
                    ProcessStartInfo psi = new ProcessStartInfo();

                    psi.FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\cmd.exe");
                    psi.Arguments = String.Format("/c runas /user:{0} /savecred \"{1}\"", dialog.User, Application.ExecutablePath);
                    psi.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);

                    psi.UseShellExecute = true;

                    Process process = new Process
                    {
                        StartInfo = psi
                    };

                    if (process.Start())
                    {
                        process.WaitForExit();

                        using (ShellLink shortcut = new ShellLink())
                        {
                            //C:\Windows\System32\schtasks.exe /RUN /TN "USer2\SharpUAC"

                            shortcut.Target = @"%SystemRoot%\System32\cmd.exe";
                            shortcut.Arguments = String.Format("/c runas /user:{0} /savecred \"{1}\"", dialog.User, Application.ExecutablePath);
                            shortcut.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath); ;
                            shortcut.Description = String.Format("{0} Elevated Shortcut", S_FOLDER);
                            shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmMinimized;

                            //shortcut.IconPath = icon;
                            //shortcut.IconIndex = index;
                            //shortcut.DisplayMode = sl.DisplayMode;
                            //shortcut.HotKey = sl.HotKey;

                            String lnkPath = Path.Combine(
                                Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                                String.Format("[{0}] {1}.lnk",
                                Path.GetFileName(Application.ExecutablePath),
                                String.Format("Run as {0}", dialog.User)));

                            shortcut.Save(lnkPath);
                        }

                        Application.Exit();
                    }
                }
                catch (Exception e1)
                {
                    MessageBox.Show(e1.Message, e1.GetType().Name);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /// <summary>
        /// Event handler. Called by Form1 for load events.
        /// </summary>
        ///
        /// <param name="sender"> Source of the event. </param>
        /// <param name="e">      Event information. </param>
        private void Form1_Load(object sender, EventArgs e)
        {
            if (!SharpUACHelper.IsAdmin())
            {
                SharpUACHelper.AddShieldToButton(ByTaskBtn);

                this.UACToolTip.ToolTipTitle = "UAC";
                this.UACToolTip.SetToolTip(ByTaskBtn,
                String.Format("\r\nFor Vista and Windows 7/8/10 Users:\r\n\r\n" +
                    "{0} requires admin rights for device removal.\r\n" +
                    "If you click this button {0} will restart and ask for these rights.", SharpUACHelper.S_TITLE));
            }

            label1.Text = SharpUACHelper.IsAdmin() ? "Running as Admin" : "Running Unelevated";

            foreach (String file in Directory.GetFiles(Path.GetDirectoryName(Application.ExecutablePath), "*.lnk"))
            {
                listView2.Items.Add(Path.GetFileNameWithoutExtension(file)).Tag = file;
            }
        }

        private void Impersonate(String shortcut)
        {
            //! 1) Extract info from *.lnk.
            //
            ShellLink sl = new ShellLink(shortcut);

            String appl = sl.Target;
            String args = sl.Arguments;
            String workdir = sl.WorkingDirectory;
            String uactask = Path.GetFileNameWithoutExtension(sl.ShortCutFile);

            //! 2) Show extracted information.
            //
            listView1.Items.Clear();
            listView1.Groups.Clear();

            ListViewGroup lvg = new ListViewGroup(uactask);
            listView1.Groups.Add(lvg);

            lvg.Items.Add(listView1.Items.Add("Link")).SubItems.Add(shortcut);
            lvg.Items.Add(listView1.Items.Add("Application")).SubItems.Add(appl);
            lvg.Items.Add(listView1.Items.Add("Arguments")).SubItems.Add(args);
            lvg.Items.Add(listView1.Items.Add("WorkingDirectory")).SubItems.Add(workdir);

            listView1.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            listView1.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);

            using (UserCredentialsDialog dialog = new UserCredentialsDialog())
            {
                // Debug.Print(dialog.MachineName);

                dialog.LoadCredentials("localhost", false);

                String user = dialog.User;
                String domain = dialog.Domain;

                dialog.Domain = String.Empty;

                if (!dialog.CredentialsExist("SharpUAC"))
                {
                    dialog.SaveChecked = true;

                    if (dialog.ShowDialog(this) == DialogResult.OK && dialog.SaveChecked)
                    {
                        //! Check credentials...
                        //
                        dialog.StoreCredentials(true);
                    }
                    else
                    {
                        return;
                    }
                }

                dialog.LoadCredentials("SharpUAC");

                lvg.Items.Add(listView1.Items.Add("Impersonating")).SubItems.Add(dialog.User);

                ImpersonateAsUtil.ImpersonateAsExecute(shortcut, dialog.User, dialog.PasswordToString());

                //ImpersonateAsUtil.ImpersonateAsExecute(shortcut, dialog.User, dialog.PasswordToString());
            }
        }

        /// <summary>
        /// Loads a shortcut executes it while impersonating a used with stored
        /// credentials of an elevated user.
        /// </summary>
        ///
        /// <param name="sender"> Source of the event. </param>
        /// <param name="e">      Event information. </param>
        private void ImpersonateBtn_Click(object sender, EventArgs e)
        {
            // use RunAs with /SaveCred. We should pipe the password into the cmdline when asked.
            // use RunAs verb.

            //http://stackoverflow.com/questions/133379/elevating-process-privilege-programatically

            //  WindowsIdentity identity = new WindowsIdentity(accessToken);
            //  WindowsImpersonationContext context = identity.Impersonate();
            //ImpersonationUtils.LaunchAsCurrentUser("notepad");

            //using (ImpersonationUtils.ImpersonateCurrentUser())
            //{

            //}

            // See https://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext(v=vs.110).aspx
            // See http://www.pinvoke.net/default.aspx/advapi32/createprocessasuser.html
            // See http://stackoverflow.com/questions/125341/how-do-you-do-impersonation-in-net

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                listView1.Items.Clear();
                foreach (String shortcut in openFileDialog1.FileNames)
                {
                    Impersonate(shortcut);
                }
            }
        }

        private void impersonateMnu_Click(object sender, EventArgs e)
        {
            if (listView2.SelectedItems != null && listView2.SelectedItems.Count == 1)
            {
                Impersonate((String)listView2.SelectedItems[0].Tag);
            }
        }

        private void listView2_SelectedIndexChanged(object sender, EventArgs e)
        {
            Boolean go = (listView2.SelectedItems != null && listView2.SelectedItems.Count == 1);

            ImpersonateBtn.Enabled = go;
            RunAsBtn.Enabled = go;
            impersonateToolStripMenuItem.Enabled = true;
            runAsToolStripMenuItem.Enabled = true;
        }

        /// <summary>
        /// Loads a shortcut executes it with the 'runas' verb with stored
        /// credentials of an elevated user.
        /// </summary>
        ///
        /// <param name="sender"> Source of the event. </param>
        /// <param name="e">      Event information. </param>
        private void RunAsBtn_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                listView1.Items.Clear();
                foreach (String shortcut in openFileDialog1.FileNames)
                {
                    StartTask(shortcut);
                }
            }
        }

        private void runAsMnu_Click(object sender, EventArgs e)
        {
            if (listView2.SelectedItems != null && listView2.SelectedItems.Count == 1)
            {
                StartTask((String)listView2.SelectedItems[0].Tag);
            }
        }

        private void setCredentialsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx
            // See https://msdn.microsoft.com/en-us/library/aa480470.aspx#cred_topic5

            using (UserCredentialsDialog dialog = new UserCredentialsDialog())
            {
                dialog.Target = "SharpUAC"; // kind of Domain / username prefix
                dialog.Caption = "Enter your Credentials";
                dialog.Message = "Enter the credentials needed to elevate using UAC";
                dialog.User = "initial user name";
                //dialog.Banner = Images.Banner;

                //dialog.AlwaysShowUI = true;
                //dialog.CompleteUserName = true;
                //dialog.ExpectConfirmation = true;
                //dialog.GenericCredentials = true;
                //dialog.IncorrectPassword = true;
                //dialog.Persist = true;
                //dialog.RequestAdministrator = true;
                //dialog.ValidateUserName = true;

                dialog.LoadCredentials("SharpUAC");
                dialog.SaveChecked = true;

                if (dialog.ShowDialog(this) == DialogResult.OK && dialog.SaveChecked)
                {
                    //! Check credentials...
                    //
                    dialog.StoreCredentials(true);
                }
            }
        }

        /// <summary>
        /// Starts a task.
        /// </summary>
        ///
        /// <param name="shortcut"> The shortcut. </param>
        private void StartTask(String shortcut)
        {
            ShellLink sl = new ShellLink(shortcut);

            String appl = sl.Target;
            String args = sl.Arguments;
            String workdir = sl.WorkingDirectory;
            String uactask = Path.GetFileNameWithoutExtension(shortcut);

            //! 2) Show extracted information.
            //
            listView1.Items.Clear();
            listView1.Groups.Clear();

            ListViewGroup lvg = new ListViewGroup(uactask);
            listView1.Groups.Add(lvg);

            lvg.Items.Add(listView1.Items.Add("Link")).SubItems.Add(shortcut);
            lvg.Items.Add(listView1.Items.Add("Application")).SubItems.Add(appl);
            lvg.Items.Add(listView1.Items.Add("Arguments")).SubItems.Add(args);
            lvg.Items.Add(listView1.Items.Add("WorkingDirectory")).SubItems.Add(workdir);

            listView1.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            listView1.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);

            using (UserCredentialsDialog dialog = new UserCredentialsDialog())
            {
                // Debug.Print(dialog.MachineName);

                dialog.LoadCredentials("localhost", false);

                String user = dialog.User;
                String domain = dialog.Domain;

                dialog.Domain = String.Empty;

                if (!dialog.CredentialsExist("SharpUAC"))
                {
                    dialog.SaveChecked = true;

                    if (dialog.ShowDialog(this) == DialogResult.OK && dialog.SaveChecked)
                    {
                        //! Check credentials...
                        //
                        dialog.StoreCredentials(true);
                    }
                    else
                    {
                        return;
                    }
                }

                dialog.LoadCredentials("SharpUAC");

                try
                {
                    lvg.Items.Add(listView1.Items.Add("Running as")).SubItems.Add(dialog.User);

                    ProcessStartInfo psi = new ProcessStartInfo();
                    psi.Verb = "runas";
                    psi.FileName = appl;
                    psi.UserName = dialog.User; //String.Format(@"{0}\{1}",  );
                    psi.Domain = String.Empty;
                    psi.Password = dialog.Password;
                    psi.Arguments = args;
                    psi.WorkingDirectory = workdir;
                    psi.UseShellExecute = false;

                    Process.Start(psi);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, e.GetType().Name);
                }
            }

            // See http://stackoverflow.com/questions/3936456/process-start-impersonation-problem
        }

        private void visitWebsiteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ClickOnceUpdater.VisitWebsite("http://sharpuac.codeplex.com/");
        }

        #endregion Methods
    }

    /// <summary>
    /// A sharp UAC helper.
    /// </summary>
    public static class SharpUACHelper
    {
        #region Fields

        /// <summary>
        /// The title.
        /// </summary>
        public static readonly String S_TITLE = "SharpUAC";

        /// <summary>
        /// .
        /// </summary>
        public static readonly String S_URL = "http://sharpuac.codeplex.com";

        /// <summary>
        /// Normal button.
        /// </summary>
        internal const int BCM_FIRST = 0x1600;

        /// <summary>
        /// Elevated button.
        /// </summary>
        internal const int BCM_SETSHIELD = (BCM_FIRST + 0x000C);

        #endregion Fields

        #region Methods

        /// <summary>
        /// Adds a shield to button.
        /// </summary>
        ///
        /// <param name="b"> The b control. </param>
        internal static void AddShieldToButton(Button b)
        {
            b.FlatStyle = FlatStyle.System;
            SendMessage(b.Handle, BCM_SETSHIELD, 0, 0xFFFFFFFF);
        }

        /// <summary>
        /// Query if this object is admin.
        /// </summary>
        ///
        /// <returns>
        /// true if admin, false if not.
        /// </returns>
        internal static bool IsAdmin()
        {
            WindowsIdentity user = WindowsIdentity.GetCurrent();
            WindowsPrincipal principal = new WindowsPrincipal(user);

            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }

        /// <summary>
        /// Restart elevated.
        /// </summary>
        ///
        /// <param name="fileName"> Filename of the file. </param>
        internal static void RestartElevated(String fileName)
        {
            ProcessStartInfo processInfo = new ProcessStartInfo();
            processInfo.Verb = "runas";
            processInfo.FileName = fileName;
            try
            {
                Process.Start(processInfo);

                Application.Exit();
            }
            catch (Win32Exception)
            {
                //Do nothing. Probably the user canceled the UAC window
            }
        }

        /// <summary>
        /// Sends a message.
        /// </summary>
        ///
        /// <param name="hWnd">   The window. </param>
        /// <param name="msg">    The message. </param>
        /// <param name="wParam"> The parameter. </param>
        /// <param name="lParam"> The parameter. </param>
        ///
        /// <returns>
        /// An UInt32.
        /// </returns>
        [DllImport("user32")]
        internal static extern UInt32 SendMessage(IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);

        #endregion Methods
    }
}